﻿using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.Serialization;

using Injectors.Core.Attributes.Generic;

using Mono.Cecil;

namespace Injectors.Core.Attributes
{
	[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
	[Serializable]
	public sealed class DataContractInjectorAttribute : InjectorAttribute<TypeDefinition>
	{
		[SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
		protected override void OnInject(TypeDefinition target)
		{
			if (target == null)
			{
				throw new NullReferenceException("target");
			}

			var attrConstructor = target.Module.Import(typeof(DataMemberAttribute).GetConstructor(Type.EmptyTypes));
			var contractConstructor = target.Module.Import(typeof(System.Runtime.Serialization.DataContractAttribute).GetConstructor(Type.EmptyTypes));

			if (target.CustomAttributes.OfType<System.Runtime.Serialization.DataContractAttribute>().Any())
			{
				return;
			}
			target.CustomAttributes.Add(new CustomAttribute(contractConstructor));

			if (target.Properties.Any(p => p.CustomAttributes.OfType<DataMemberAttribute>().Any()))
			{
				throw new InvalidOperationException("Data Member attribute exists in injector target properties");
			}
			foreach (var p in target.Properties)
			{
				p.CustomAttributes.Add(new CustomAttribute(attrConstructor));
			}
		}
	}
}